package com.example.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo.dao.ParameterDao;
import com.example.demo.domain.entity.ParameterEntity;
import com.example.demo.domain.model.Parameter;
import com.example.demo.domain.model.ParameterDefinition;
import com.example.demo.domain.model.ParameterValue;
import com.example.demo.service.ParameterVerifyService;
import com.example.demo.service.exception.ParameterVerifyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class ParameterVerifyServiceImpl implements ParameterVerifyService {
    @Autowired
    ParameterDao parameterDao;

    @Override
    public void validate(Parameter parameter) {
        Assert.notNull(parameter.getOperatorType(),"parameter operatorType is null");
        validateSelf(parameter);
        if("update".equals(parameter.getOperatorType())){
            return;
        }
        validateByDB(parameter);
    }

    @Override
    public void validateSelf(Parameter parameter) {
        validateNotNull(parameter.getCode(), "Parameter code must not null!");
        validateNotNull(parameter.getName(), "Parameter name must not null!");
        for (ParameterDefinition parameterDefinition : parameter.getParameterDefinitions()) {
            String code = parameterDefinition.getCode();
            String name = parameterDefinition.getName();
            validateNotNull(code, "parameterDefinition code must not null!");
            validateNotNull(name, "parameterDefinition name must not null!");
        }
        for (ParameterValue parameterValue : parameter.getParameterValues()) {
            String code = parameterValue.getCode();
            String name = parameterValue.getName();
            validateNotNull(code, "parameterValue code must not null!");
            validateNotNull(name, "parameterValue name must not null!");
        }
        validateParameterDefinitionUnique(parameter.getParameterDefinitions());
        validateParameterValuesUnique(parameter.getParameterValues());
    }

    private void validateParameterDefinitionUnique(List<ParameterDefinition> parameterDefinitions) {
        int nameSize = parameterDefinitions.stream().map(ParameterDefinition::getCode).collect(Collectors.toSet()).size();
        int codeSize = parameterDefinitions.stream().map(ParameterDefinition::getName).collect(Collectors.toSet()).size();
        int size = parameterDefinitions.size();
        boolean isRepeat = size != nameSize || size != codeSize;
        if (isRepeat) {
            throw new ParameterVerifyException("validateParameterDefinitionUnique failure!");
        }
    }

    private void validateParameterValuesUnique(List<ParameterValue> parameterValues) {
        int nameSize = parameterValues.stream().map(ParameterValue::getCode).collect(Collectors.toSet()).size();
        int codeSize = parameterValues.stream().map(ParameterValue::getName).collect(Collectors.toSet()).size();
        int size = parameterValues.size();
        boolean isRepeat = size != nameSize || size != codeSize;
        if (isRepeat) {
            throw new ParameterVerifyException("validateParameterValuesUnique failure!");
        }
    }

    @Override
    public void validateByDB(Parameter parameter) {
        validateNameUniqueByDB(parameter);
        validateCodeUniqueByDB(parameter);
    }

    private void validateNameUniqueByDB(Parameter parameter) {
        String name = parameter.getName();
        LambdaQueryWrapper<ParameterEntity> qname = Wrappers.lambdaQuery(ParameterEntity.class).eq(ParameterEntity::getName, name);
        Integer count = parameterDao.selectCount(qname);
        if (count != 0) {
            throw new ParameterVerifyException(String.format("name %s 不唯一 ", name));
        }
    }

    private void validateCodeUniqueByDB(Parameter parameter) {
        String code = parameter.getCode();
        LambdaQueryWrapper<ParameterEntity> qcode = Wrappers.lambdaQuery(ParameterEntity.class).eq(ParameterEntity::getCode, code);
        Integer count = parameterDao.selectCount(qcode);
        if (count != 0) {
            throw new ParameterVerifyException(String.format("code %s 不唯一 ", code));
        }
    }

    private void validateNotNull(String str, String m) {
        if (str == null || "".equals(str.trim())) {
            throw new ParameterVerifyException(m);

        }
    }
}
